package com.neusoft.elmboot.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neusoft.elmboot.exception.exceptions.BaseException;
import com.neusoft.elmboot.exception.exceptions.ErrorStateException;
import com.neusoft.elmboot.exception.exceptions.IllegalAmountException;
import com.neusoft.elmboot.mapper.WalletMapper;
import com.neusoft.elmboot.po.vo.WalletTransactionVO;
import com.neusoft.elmboot.po.wallet.VirtualWallet;
import com.neusoft.elmboot.po.wallet.WalletTransaction;
import com.neusoft.elmboot.service.WalletService;
import com.neusoft.elmboot.util.WalletUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class WalletServiceImpl extends ServiceImpl<WalletMapper, VirtualWallet> implements WalletService {
    @Resource
    private WalletMapper walletMapper;

    @Resource
    private BCryptPasswordEncoder encoder;

    private void checkWallet(VirtualWallet wallet) throws BaseException {
        if (wallet == null) {
            throw new ErrorStateException("用户不存在");
        }
    }

    @Override
    public Integer init(String walletId, String payPwd) throws BaseException {
        if (walletId == null || payPwd == null){
            throw new ErrorStateException("用户或密码为空");
        } else if (walletMapper.selectById(walletId) != null) {
            throw new ErrorStateException("用户已存在");
        } else {
            payPwd = encoder.encode(payPwd);
            VirtualWallet wallet = new VirtualWallet(walletId, payPwd);
            return walletMapper.insert(wallet);
        }
    }

    @Override
    public void setVIP(List<String> walletIdList) throws BaseException {
        if (walletIdList.isEmpty()) {
            throw new ErrorStateException("用户不能为空");
        } else {
            walletMapper.setVIP(walletIdList);
        }
    }

    @Override
    public void setOverdraftAmount(String walletId, BigDecimal amount) throws BaseException{
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            throw new ErrorStateException("用户为空");
        } else if (amount.compareTo(WalletUtils.minOverdraftAmount) < 0 || amount.compareTo(WalletUtils.maxOverdraftAmount) > 0) {
            throw new IllegalAmountException("金额异常");
        } else {
            if (!wallet.getIsVIP()) {
                throw new ErrorStateException("非VIP不能透支");
            } else {
                walletMapper.setOverdraftAmount(walletId, amount);
            }
        }
    }

    @Override
    public VirtualWallet getInfo(String walletId) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        checkWallet(wallet);
        wallet.hidePwd();
        return wallet;
    }

    @Override
    public List<WalletTransactionVO> getTransInfo(String walletId, Integer index) throws Exception {
        if (walletMapper.selectById(walletId) == null) {
            throw new ErrorStateException("用户不存在");
        } else {
            if (index.equals(WalletUtils.incomeIndex)) {
                return walletMapper.getIncomeTrans(walletId);
            } else if (index.equals(WalletUtils.outcomeIndex)) {
                return walletMapper.getOutcomeTrans(walletId);
            } else {
                return walletMapper.getTransByWalletId(walletId);
            }
        }
    }

    @Override
    public void recharge(String walletId, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            throw new ErrorStateException("用户不存在");
        } else if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalAmountException("充值金额异常");
        } else {
            if (wallet.getIsVIP() && !wallet.getIsAllowedOverdraft()) {
                throw new ErrorStateException("请先还款");
            } else {
                WalletTransaction transaction = new WalletTransaction(walletId, walletId, amount);
                transaction.unfreeze();
                BigDecimal levels = amount.divide(BigDecimal.valueOf(WalletUtils.rechargeLevel), RoundingMode.FLOOR);
                BigDecimal extra = levels.multiply(BigDecimal.valueOf(WalletUtils.rechargeGift));
                amount = amount.add(extra);
                walletMapper.recharge(walletId, amount);
                walletMapper.addTrans(transaction);
            }
        }
    }

    @Override
    public void repay(String walletId, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            throw new ErrorStateException("用户不存在");
        } else {
            wallet.repay(amount);
            walletMapper.updateById(wallet);
        }
    }

    @Override
    public BigDecimal withdraw(String walletId, String payPwd, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        checkWallet(wallet);
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalAmountException("提现金额异常");
        } else {
            WalletTransaction transaction = new WalletTransaction(walletId, walletId, amount);
            transaction.unfreeze();
            String encodedPwd = wallet.getPayPwd();
            BigDecimal balance = wallet.getBalance();
            if (amount.compareTo(balance) > 0) {
                throw new IllegalAmountException("余额不足，无法提现");
            } else if (wallet.getCurrentOverdraftAmount().compareTo(BigDecimal.ZERO) > 0) {
                throw new ErrorStateException("请先还款");
            } else if (!BCrypt.checkpw(payPwd, encodedPwd)){
                throw new ErrorStateException("密码错误");
            } else {
                balance = balance.subtract(amount);
                walletMapper.withdraw(walletId, balance);
                walletMapper.addTrans(transaction);
                return balance.multiply(BigDecimal.valueOf(WalletUtils.withdrawRate));
            }
        }
    }

    @Override
    public String pay(String fromWalletId, String toWalletId, String payPwd, BigDecimal amount) throws BaseException {
        if (walletMapper.selectById(fromWalletId) == null || walletMapper.selectById(toWalletId) == null){
            throw new ErrorStateException("交易对象异常");
        } else if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalAmountException("交易金额异常");
        } else {
            VirtualWallet fromWallet = walletMapper.selectById(fromWalletId);
            String encodedPwd = fromWallet.getPayPwd();
            if (fromWallet.getIsVIP() && !fromWallet.getIsAllowedOverdraft()) {
                throw new ErrorStateException("请先还款");
            } else if (!BCrypt.checkpw(payPwd, encodedPwd)){
                throw new ErrorStateException("密码错误");
            } else {
                VirtualWallet toWallet = walletMapper.selectById(toWalletId);
                WalletTransaction transaction = new WalletTransaction(fromWalletId, toWalletId, amount);
                fromWallet.debit(amount);
                toWallet.freeze(amount);
                walletMapper.updateById(fromWallet);
                walletMapper.updateById(toWallet);
                walletMapper.addTrans(transaction);
                return transaction.getTransId();
            }

        }
    }

    @Override
    public void confirm(String transId) throws BaseException{
        WalletTransaction transaction = walletMapper.getTrans(transId);
        if (transaction == null) {
            throw new ErrorStateException("订单不存在");
        } else {
            if (!transaction.getIsValid()) {
                throw new ErrorStateException("订单失效");
            } else {
                VirtualWallet toWallet = walletMapper.selectById(transaction.getToWalletId());
                toWallet.unfreeze(transaction.getAmount());
                toWallet.credit(transaction.getAmount());
                transaction.unfreeze();
                walletMapper.updateById(toWallet);
                walletMapper.updateTransState(transId,false, null);
            }
        }
    }


//    @Scheduled(cron = "0/10 * * * * ?")
    @Scheduled(cron = "0 0 4 * * ?")
    public void cleanFrozenTrans() throws BaseException{
        List<String> frozenTransList = walletMapper.getFrozenTransId();

        for (String transId : frozenTransList) {
            confirm(transId);
            log.info(transId);
        }
    }
    

//    @Scheduled(cron = "0/10 * * * * ?")
    @Scheduled(cron = "0 0 4 * * ?")
    public void updateRepayAmount() throws BaseException{
        List<String> overdraftIdList = walletMapper.getOverdraftId();
        for (String id : overdraftIdList) {
            VirtualWallet wallet = walletMapper.selectById(id);
            checkWallet(wallet);
            if (!wallet.getIsVIP()) {
                throw new ErrorStateException("用户VIP状态异常");
            } else {
                BigDecimal cur = wallet.getCurrentOverdraftAmount();
                cur = cur.add(cur.multiply(BigDecimal.valueOf(WalletUtils.DailyInterestRate)));
                wallet.setCurrentOverdraftAmount(cur);
                walletMapper.updateById(wallet);
                log.info(String.valueOf(wallet.getCurrentOverdraftAmount()));
            }
        }
    }

}
